package com.sisgh.jefdv1.core.jdbc.connection.properties;

import com.mysql.cj.util.StringUtils;
import com.sisgh.jefdv1.core.jdbc.db.Database;
import lombok.Data;

import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 连接属性类
 */
@Data
public class ConnectionProperties {

    /**
     * url 中 参数名和参数符号
     */
    private static final char PARAM_SEPARATOR = '&';
    private static final String PARAM_USER = "user";
    private static final String PARAM_PASSWORD = "password";
    private static final char PARAM_START = '?';

    /**
     * 枚举值，用于判断 user 和 pwd 所处位置，从而使用不同的 getConnection()
     */
    public static final int URL_INVALIDATE = 0;
    public static final int URL_HAS_USER_PWD = 1;
    public static final int URL_NOT_USER_PWD = 2;
    public static final int PROPERTIES_HAS_USER_PWD = 3;

    /**
     * 基础属性
     */
    private String url;
    private String username;
    private String password;
    private Properties properties;

    public ConnectionProperties(String url, String username, String password, Properties properties) {
        this.url = StringUtils.safeTrim(url);
        this.username = StringUtils.safeTrim(username);
        this.password = StringUtils.safeTrim(password);
        this.properties = properties;
    }

    public ConnectionProperties(String url, String username, String password) {
        this(url, username, password, null);
    }

    public ConnectionProperties(String url) {
        this(url, null, null, null);
    }

    /**
     * 判断 url 是否存在参数
     * @return
     */
    private boolean urlHasParams() {
        int start = url.indexOf(PARAM_SEPARATOR);
        return start != -1;
    }

    /**
     * 判断 url 是否存在参数  param
     * @param param
     * @return
     */
    private boolean urlHasParams(String param) {
        int start = url.indexOf(param);
        if (start == -1) {
            return false;
        }

        start = start + param.length();
        int end = url.indexOf(PARAM_SEPARATOR, start);
        return end != -1 && start + 1 != end;
    }

    /**
     * 获取 url 参数之前的 url
     * @return
     */
    public String getShortestUrl() {
        int i = url.lastIndexOf('?');
        if (i == -1) {
            return url;
        }
        return url.substring(0, i);
    }

    /**
     * 判断url是否有效
     * @param db
     * @return
     */
    private boolean urlIsValidate(Database db) {
        if (url == null) {
            return false;
        }
        Pattern pattern = Pattern.compile(db.getPattern());
        Matcher matcher = pattern.matcher(getShortestUrl());
        return matcher.matches();
    }

    /**
     * 判断properties是否存在对应属性
     * @param param
     * @return
     */
    private boolean propertiesHasParams(String... param) {
        if (properties == null || properties.isEmpty()) {
            return false;
        }

        boolean res = true;
        for (String p : param) {
            res &= (this.properties.getProperty(p) != null);
        }
        return res;
    }

    /**
     * 判断url是否有效
     * @param db
     * @return
     */
    public int validate(Database db) {
        // url有效
        if (!urlIsValidate(db)) {
            return URL_INVALIDATE;
        }

        // 是否包含参数 user 和 password
        boolean hasUser = urlHasParams(PARAM_USER);
        boolean hasPassword = urlHasParams(PARAM_PASSWORD);

        if (hasUser && hasPassword) {
            // 都包含
            return URL_HAS_USER_PWD;
        } else if (hasUser || hasPassword) {
            // 部分包含
            return URL_INVALIDATE;
        } else {
            // 在 properties 中
            if (propertiesHasParams(PARAM_USER, PARAM_PASSWORD)) {
                return PROPERTIES_HAS_USER_PWD;
            }
            // 不包含
            return URL_NOT_USER_PWD;
        }
    }
}
